package TextGeneration;

import java.util.ArrayList;

import ruletree.rule.Action;
import ruletree.rule.RuleList;

import components.Component;
import components.Leaf;
import components.Phrase;
import features.Feature;

import ruletree.rule.Rule;

public class Unification {
	
	public static ArrayList<ArrayList<Component>> unifyAll(Rule rule, ArrayList<Component> semReps){
		ArrayList<ArrayList<Component>> applyRuleHere = new ArrayList<>();
		ArrayList<Component> patterns = rule.getChildrenList().getChildren();
		
		for(Component pattern: patterns){
			ArrayList<Component> componentCheck = semReps;
			for(Component semRep : componentCheck){
				ArrayList<Component> check = new ArrayList<>();
				check = unify(pattern, semRep);
				
				if(check != null){
					applyRuleHere.add(check);
				}
			}
		}
		return applyRuleHere;
	}
	
	public static ArrayList<Component> unify(Component rule, Component semRep) {
		ArrayList<Component> newResults = new ArrayList<>();
		if(rule.getName()== null) // added this line of code, nagkakerror kasi kanina kapag wala
			return null;
		if (!(rule.getName().equalsIgnoreCase(semRep.getName()))) {
			return null;
		} else {
			//System.out.println(rule.getName());
			ArrayList<Feature> ruleFeatureList = rule.getFeatureList();
			int count = 0;
			for (Feature feature : ruleFeatureList) {
				Boolean match = false;
				ArrayList<Feature> semFeatureList = semRep.getFeatureList();
				//System.out.println(feature.getName() +  " = " + feature.getValue());
				for (Feature feat : semFeatureList) {
					//System.out.println(feat.getName() +"="+feat.getValue()+" "+feature.getName().equalsIgnoreCase(feat.getName()) + feature.getValue().equalsIgnoreCase(feat.getValue()));
			
					if (feature.getName().equalsIgnoreCase(feat.getName()) && feature.getValue().equalsIgnoreCase(feat.getValue())){
						System.out.println(feat.getName() + " = " + feat.getValue()+ " " + (feature.getName().equalsIgnoreCase(feat.getName()) && feature.getValue().equalsIgnoreCase(feat.getValue())));
						count++;
					}
				}
				
				if (count != ruleFeatureList.size()) // match == false
					return null;
			}

			if(rule.getVar() != null){
				semRep.setVar(rule.getVar());
			}

			ArrayList<Component> ruleChildren = new ArrayList<>();
			if (rule.getChildren() != null) {
				ruleChildren = rule.getChildren().getChildren();
			}
			for (Component r : ruleChildren) {
				Boolean match = false;
				ArrayList<Component> semChildren = semRep.getChildren().getChildren();
				int countSem = 0;
				for (Component s : semChildren) {
					ArrayList<Component> thisResult = new ArrayList<>();
					thisResult = unify(r, s);
					if (thisResult != null) {
						for (Component tr : thisResult) {
							newResults.add(tr);
						}
						countSem++;
					}

				}
				if (countSem != semChildren.size()) {
					return null;
				}
			}
			
			if(rule.getVar() != null){
				ArrayList<Component> var = new ArrayList<>();
				var.add(semRep);
				
				for(Component s: var)
					newResults.add(s);

				return newResults;
			}
			else
				return newResults;

		}

		//return newResults;
	}

	public static Component applyOutputActions(ArrayList<Action> outputActions, Component varAssignments){
		for(Action action: outputActions){
			if(action.getActionName().equalsIgnoreCase("addFeature")){
				return action.addFeature(varAssignments);
			} else if (action.getActionName().equalsIgnoreCase("changeFeature")){
				return action.changeFeature(varAssignments);
			}
			else if(action.getActionName().equalsIgnoreCase("addConstituent")){
				return action.addConstituent(varAssignments);
			}
			else if(action.getActionName().equalsIgnoreCase("orderSubconstituents")){
				return action.orderSubconstituents(varAssignments);
			}
			else if(action.getActionName().equalsIgnoreCase("selectForm")){
				return action.selectForm(varAssignments);
			}
		}
		return null;
	}
	
	public static Component applyRule(Rule rule, Component semRep){
		ArrayList<Component> varAssignments = unify(rule.getChildrenList().getChildren().get(0), semRep);
		/*
		if(varAssignments != null)
		for(Component c : varAssignments)
			System.out.println(c.getName() + " VarAssignments");
		*/
		Component modifiedInput = null;

		if(varAssignments != null){
			
			for(Component component : varAssignments){
				modifiedInput = applyOutputActions(rule.getActionList(), component);
			}
		}
		/*
		System.out.println(semRep.getChildren().getChildren().size());
		for(Component subconstit : semRep.getChildren().getChildren()){
			modifiedInput = applyRule(rule, subconstit);
		}
		*/
		
		return modifiedInput;
	}
	
	public static Component applyRules(RuleList ruleList, Component semRep){
		Component modified = null;
		Component current = null;
		Component modifiedChild = null;
		System.out.println("Rules Applied:");
		for(Rule r : ruleList.getRuleList()){
			//System.out.println(r.getName());
			modified = applyRule(r, semRep);
			if(modified != null){
				System.out.println(r.getName());
				current = modified;
			}
		}
		
		return current;
	}
}
